package ace.cmp.id.generator.snowflake.builder;

import ace.cmp.id.generator.api.LongIdGenerator;
import ace.cmp.id.generator.snowflake.impl.SnowflakeImpl;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import lombok.extern.slf4j.Slf4j;

/**
 * @author Caspar
 * @create 2020/12/9 snowflake sequence auto build by network interface v4 third and fourth part
 */
@Slf4j
public class SnowflakeHostIPBuilder implements SnowflakeBuilder {
  private static final String LOCAL_IP = "127.0.0.1";

  public LongIdGenerator build() {
    String[] ips = getHostIP().split("\\.");
    Integer hightIp = Integer.valueOf(ips[2]);
    Integer lowtIp = Integer.valueOf(ips[3]);
    hightIp = hightIp * 255;
    Integer allValue = hightIp + lowtIp;
    Integer dataCenterId = allValue % 1024 / 32;
    Integer workerId = allValue % 1024 % 32;

    return new SnowflakeImpl(dataCenterId, workerId);
  }

  public static void main(String[] args) {
    SnowflakeHostIPBuilder builder = new SnowflakeHostIPBuilder();
    builder.build();
  }

  private String getHostIP() {

    Enumeration<NetworkInterface> allNetInterfaces = null;
    String resultIP = null;
    try {
      allNetInterfaces = NetworkInterface.getNetworkInterfaces();
    } catch (Throwable e) {
      log.error("无法获取本机网络接口", e);
      throw new RuntimeException("无法获取本机网络接口", e);
    }
    InetAddress ip = null;
    while (allNetInterfaces.hasMoreElements()) {
      NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
      Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
      while (addresses.hasMoreElements()) {
        ip = (InetAddress) addresses.nextElement();
        if (ip != null && ip instanceof Inet4Address) {
          if (resultIP == null && LOCAL_IP.equals(ip.getHostAddress()) == false) {
            resultIP = ip.getHostAddress();
            return resultIP;
          }
        }
      }
    }
    if (resultIP == null) {
      return "0.0.0.0";
    }
    return resultIP;
  }
}
